package com.zerowidth.moc.web.controller.serviceimpl;

import com.aliyuncs.CommonResponse;
import com.zerowidth.db.bean.*;
import com.zerowidth.db.op.*;
import com.zerowidth.db.utils.TimeUtils;
import com.zerowidth.moc.web.auth.TokenHelper;
import com.zerowidth.moc.web.bean.LoginUserVM;
import com.zerowidth.moc.web.common.SMSHelper;
import com.zerowidth.moc.web.controller.service.AccountService;
import com.zerowidth.moc.web.resp.ResCode;
import com.zerowidth.moc.web.resp.ResultBean;
import com.zerowidth.moc.web.resp.helper.ResponseCreator;
import com.zerowidth.moc.web.utils.*;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import jakarta.servlet.http.HttpServletRequest;
import java.util.*;

@Service
public class AccountServiceImpl implements AccountService {

    //每个ip每天允许发送验证码短信的条数
    private static final int MAX_SMS_COUNT_IP = 10;
    //每个手机号每天允许发送验证码短信的条数
    private static final int MAX_SMS_COUNT_PHONE = 5;

    @Override
    public ResponseEntity<ResultBean<LoginUserVM>> login(String phone, String authCode,
                                                         String pwd_key_md5, String brand, String model) {
        //检查手机号与验证码是否匹配
        if (StringUtils.length(authCode) > 0 && !SMS_DB.checkAuthCodeLogin(phone, authCode)) {
            return ResponseCreator.creatOk(null, ResCode.ER_10011, "验证码错误");
        }

        //检查此手机号是否已注册过
        UserBean userBean = UserDB.findUserByPhone(phone);
        if (userBean == null) {
            return ResponseCreator.creatOk(null, ResCode.ER_10012, "此手机号尚未注册");
        }

        //检查手机号与密码是否匹配
        if (StringUtils.length(pwd_key_md5) > 0 && !UserDB.checkPwdLogin(phone, pwd_key_md5)) {
            return ResponseCreator.creatOk(null, ResCode.ER_10013, "密码错误");
        }

        //检查此手机号是否被冻结
        FreezeUserBean freezeUserBean = FreezeUserDB.findFreeze(phone);
        if (freezeUserBean != null) {
            String errMsg = freezeUserBean.reason;
            if (StringUtils.isEmpty(errMsg)) {
                errMsg = "此账户已被冻结";
            }
            if (StringUtils.isNotEmpty(freezeUserBean.free_time)) {
                errMsg += "，解冻时间" + freezeUserBean.free_time;
            }
            return ResponseCreator.creatOk(null, ResCode.ER_10014, errMsg);
        }

        //检查是否换机登录
        MockStatBean mockStatBean = MockStatUserDB.findUserDB("", userBean.user_id);
        if (mockStatBean != null && StringUtils.isNotEmpty(brand) && StringUtils.isNotEmpty(model)
                && StringUtils.isNotEmpty(mockStatBean.brand) && StringUtils.isNotEmpty(mockStatBean.model)) {
            //具备检查换机的条件，才来判断是否换机了
            if (StringUtils.equals(brand, mockStatBean.brand) && StringUtils.equals(model, mockStatBean.model)) {
                //没有换机，可以正常继续执行
            } else {
                //检测到换机了，登录失败
                String errMsg = String.format("登录失败，检测到您已更换设备，当前账号的绑定设备类型为:%s %s。" +
                                "\n\n同一个账号不允许随意切换设备，以防止一人购买会员但却多人蹭用的场景，如需继续更换设备，请付费解绑" +
                                "\n\nuserId = %s"+
                                "\n\nstatId = %s",
                        mockStatBean.brand, mockStatBean.model, mockStatBean.user_id, mockStatBean.stat_id);

                LoginUserVM loginUserVM = new LoginUserVM();
                loginUserVM.user = userBean;

                return ResponseCreator.creatOk(loginUserVM, ResCode.ER_10015, errMsg);
            }
        }

        //////////////////////////////////////
        ///////////////  登录成功  ////////////
        // 删除 已经存在的 或 过期的 token 记录
        AuthTokenDB.clearTokenByPhone(phone);

        //创建新 token 并保存db
        AuthTokenBean newToken = new AuthTokenBean();
        newToken.user_id = userBean.user_id;
        newToken.phone_number = phone;
        newToken.auth_token = TokenHelper.createToken(userBean.user_id);
        long currentTime = System.currentTimeMillis();
        newToken.create_time = TimeUtils.convert(currentTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        long validTime = currentTime + 30 * 24 * 60 * 60 * 1000; //默认 30天 有效期
        newToken.valid_date = TimeUtils.convert(validTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        AuthTokenDB.insert(newToken);

        LoginUserVM loginUserVM = new LoginUserVM();
        loginUserVM.user = userBean;
        loginUserVM.auth_token = newToken.auth_token;
        SMS_DB.disableAuthCodeLoginRecord(phone, SMS_DB.SMS_TYPE_LOGIN); //登录成功后，清除其有效状态，防止重用

        if (userBean.vip_type > 0) {
            loginUserVM.vip_bean = VipEnumDB.findVipEnum(userBean.vip_type);
        }

        loginUserVM.baby_relation_v_m_list = BabyRelationDB.getBabyRelationVm(userBean.user_id);

        loginUserVM.stat_bean = MockStatUserDB.findUserDB("", userBean.user_id);

        return ResponseCreator.creatOk(loginUserVM, ResCode.CODE_OK, "登录成功");
    }

    @Override
    public ResponseEntity<ResultBean<LoginUserVM>> loginSNS_WX(HttpServletRequest request, String unionid, String nickname, String headimgurl) {
        String brand = request.getHeader("brand");
        String model = request.getHeader("model");

        UserBean userBean = UserDB.findUserByWXUnionid(unionid);

        if (userBean == null) {
            return ResponseCreator.creatOk(null, ResCode.ER_10016, "此微信号尚未注册");
        }

        {
            //检查此userId号是否被冻结
            FreezeUserBean freezeUserBean = FreezeUserDB.findFreezeByUserId(userBean.user_id);
            if (freezeUserBean != null) {
                String errMsg = freezeUserBean.reason;
                if (StringUtils.isEmpty(errMsg)) {
                    errMsg = "此账户已被冻结";
                }
                if (StringUtils.isNotEmpty(freezeUserBean.free_time)) {
                    errMsg += "，解冻时间" + freezeUserBean.free_time;
                }
                return ResponseCreator.creatOk(null, ResCode.ER_10014, errMsg);
            }
        }

        {
            //检查此微信号是否被冻结
            FreezeUserBean freezeUserBean = FreezeUserDB.findFreezeWXid(unionid);
            if (freezeUserBean != null) {
                String errMsg = freezeUserBean.reason;
                if (StringUtils.isEmpty(errMsg)) {
                    errMsg = "此账户已被冻结";
                }
                if (StringUtils.isNotEmpty(freezeUserBean.free_time)) {
                    errMsg += "，解冻时间" + freezeUserBean.free_time;
                }
                return ResponseCreator.creatOk(null, ResCode.ER_10014, errMsg);
            }
        }

        //检查是否换机登录
        MockStatBean mockStatBean = MockStatUserDB.findUserDB("", userBean.user_id);
        if (mockStatBean != null && StringUtils.isNotEmpty(brand) && StringUtils.isNotEmpty(model)
                && StringUtils.isNotEmpty(mockStatBean.brand) && StringUtils.isNotEmpty(mockStatBean.model)) {
            //具备检查换机的条件，才来判断是否换机了
            if (StringUtils.equals(brand, mockStatBean.brand) && StringUtils.equals(model, mockStatBean.model)) {
                //没有换机，可以正常继续执行
            } else {
                //检测到换机了，登录失败
                String errMsg = String.format("登录失败，检测到您已更换设备，当前账号的绑定设备类型为:%s %s。" +
                                "\n\n同一个账号不允许随意切换设备，以防止一人购买会员但却多人蹭用的场景，如需继续更换设备，请付费解绑" +
                                "\n\nuserId = %s"+
                                "\n\nstatId = %s",
                        mockStatBean.brand, mockStatBean.model, mockStatBean.user_id, mockStatBean.stat_id);

                LoginUserVM loginUserVM = new LoginUserVM();
                loginUserVM.user = userBean;

                return ResponseCreator.creatOk(loginUserVM, ResCode.ER_10015, errMsg);
            }
        }


        //////////////////////////////////////
        ///////////////  登录成功  ////////////
        // 删除 已经存在的 或 过期的 token 记录
        AuthTokenDB.clearTokenByUserid(userBean.user_id);

        //创建新 token 并保存db
        AuthTokenBean newToken = new AuthTokenBean();
        newToken.user_id = userBean.user_id;
        newToken.wx_unionid = unionid;
        newToken.auth_token = TokenHelper.createToken(userBean.user_id);
        long currentTime = System.currentTimeMillis();
        long validTime = currentTime + 30 * 24 * 60 * 60 * 1000; //默认 30天 有效期
        newToken.create_time = TimeUtils.convert(currentTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        newToken.valid_date = TimeUtils.convert(validTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        AuthTokenDB.insert(newToken);

        LoginUserVM loginUserVM = new LoginUserVM();
        loginUserVM.user = userBean;
        loginUserVM.auth_token = newToken.auth_token;
        loginUserVM.baby_relation_v_m_list = BabyRelationDB.getBabyRelationVm(userBean.user_id);

        loginUserVM.stat_bean = MockStatUserDB.findUserDB("", userBean.user_id);

        if (userBean.vip_type > 0) {
            loginUserVM.vip_bean = VipEnumDB.findVipEnum(userBean.vip_type);
        }

        return ResponseCreator.creatOk(loginUserVM, ResCode.CODE_OK, "登录成功");
    }

    @Override
    public ResponseEntity<ResultBean<LoginUserVM>> loginSNS_QQ(HttpServletRequest request, String unionid, String nickname, String headimgurl) {
        String brand = request.getHeader("brand");
        String model = request.getHeader("model");
        String stat_id = request.getHeader("stat_id");

        UserBean statUserBean = UserDB.findUserByQQOpenidAndStatId(stat_id);

        UserBean qqUserBean = UserDB.findUserByQQOpenid(unionid);

        if (qqUserBean == null && statUserBean != null) {
            //如果此设备id有记录，且qq没有账号，则将设备用户代替qq用户
            qqUserBean = statUserBean;
        }

        //检查此微信号是否被冻结
        {
            FreezeUserBean freezeUserBean = FreezeUserDB.findFreezeWXid(unionid);
            if (freezeUserBean != null) {
                String errMsg = freezeUserBean.reason;
                if (StringUtils.isEmpty(errMsg)) {
                    errMsg = "此账户已被冻结";
                }
                if (StringUtils.isNotEmpty(freezeUserBean.free_time)) {
                    errMsg += "，解冻时间" + freezeUserBean.free_time;
                }
                return ResponseCreator.creatOk(null, ResCode.ER_10014, errMsg);
            }
        }

        byte[] bytes = Base64.getDecoder().decode(headimgurl);
        headimgurl = new String(bytes);

        if (qqUserBean == null) {
            return ResponseCreator.creatOk(null, ResCode.ER_10017, "此QQ号尚未注册");
        }

        {
            //检查此userId号是否被冻结
            FreezeUserBean freezeUserBean = FreezeUserDB.findFreezeByUserId(unionid);
            if (freezeUserBean != null) {
                String errMsg = freezeUserBean.reason;
                if (StringUtils.isEmpty(errMsg)) {
                    errMsg = "此账户已被冻结";
                }
                if (StringUtils.isNotEmpty(freezeUserBean.free_time)) {
                    errMsg += "，解冻时间" + freezeUserBean.free_time;
                }
                return ResponseCreator.creatOk(null, ResCode.ER_10014, errMsg);
            }
        }

        //检查是否换机登录
        MockStatBean mockStatBean = MockStatUserDB.findUserDB("", qqUserBean.user_id);
        if (mockStatBean != null && StringUtils.isNotEmpty(brand) && StringUtils.isNotEmpty(model)
                && StringUtils.isNotEmpty(mockStatBean.brand) && StringUtils.isNotEmpty(mockStatBean.model)) {
            //具备检查换机的条件，才来判断是否换机了
            if (StringUtils.equals(brand, mockStatBean.brand) && StringUtils.equals(model, mockStatBean.model)) {
                //没有换机，可以正常继续执行
            } else {
                //检测到换机了，登录失败
                String errMsg = String.format("登录失败，检测到您已更换设备，当前账号的绑定设备类型为:%s %s。" +
                                "\n\n同一个账号不允许随意切换设备，以防止一人购买会员但却多人蹭用的场景，如需继续更换设备，请付费解绑" +
                                "\n\nuserId = %s"+
                                "\n\nstatId = %s",
                        mockStatBean.brand, mockStatBean.model, mockStatBean.user_id, mockStatBean.stat_id);

                LoginUserVM loginUserVM = new LoginUserVM();
                loginUserVM.user = qqUserBean;

                return ResponseCreator.creatOk(loginUserVM, ResCode.ER_10015, errMsg);
            }
        }


        //////////////////////////////////////
        ///////////////  登录成功  ////////////
        // 删除 已经存在的 或 过期的 token 记录
        AuthTokenDB.clearTokenByUserid(qqUserBean.user_id);

        //创建新 token 并保存db
        AuthTokenBean newToken = new AuthTokenBean();
        newToken.user_id = qqUserBean.user_id;
        newToken.wx_unionid = unionid;
        newToken.auth_token = TokenHelper.createToken(qqUserBean.user_id);
        long currentTime = System.currentTimeMillis();
        long validTime = currentTime + 30 * 24 * 60 * 60 * 1000; //默认 30天 有效期
        newToken.create_time = TimeUtils.convert(currentTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        newToken.valid_date = TimeUtils.convert(validTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        AuthTokenDB.insert(newToken);

        LoginUserVM loginUserVM = new LoginUserVM();
        loginUserVM.user = qqUserBean;
        loginUserVM.auth_token = newToken.auth_token;
        loginUserVM.baby_relation_v_m_list = BabyRelationDB.getBabyRelationVm(qqUserBean.user_id);

        loginUserVM.stat_bean = MockStatUserDB.findUserDB("", qqUserBean.user_id);

        if (qqUserBean.vip_type > 0) {
            loginUserVM.vip_bean = VipEnumDB.findVipEnum(qqUserBean.vip_type);
        }

        return ResponseCreator.creatOk(loginUserVM, ResCode.CODE_OK, "登录成功");
    }

    @Override
    public ResponseEntity<ResultBean<LoginUserVM>> loginUserId8(HttpServletRequest request, String userId8) {

        String brand = request.getHeader("brand");
        String model = request.getHeader("model");
        String stat_id = request.getHeader("stat_id");

        if (StringUtils.isEmpty(userId8)) {
            return ResponseCreator.creatOk(null, ResCode.ER_70014, "登录失败，请输入账号");
        }

        UserBean userBean = UserDB.findUserByUserIdLike(userId8);

        if (userBean == null) {
            String activeCode = userId8; //用户直接把 激活码当成账号来进行登录，也让他能登录成功
            userId8 = ActiveDB.findActiveUserId(activeCode);

            if (StringUtils.isNotEmpty(userId8)) {
                //首次使用激活码登录，直接从 激活码表 查找用户
                userBean = UserDB.findUserByUserIdLike(userId8);
            } else {
                //首次使用激活码登录，则自动注册
                loginAutoRegister(request);


                int activeCodeVipType = ActiveDB.findVipType(activeCode);
                if (activeCodeVipType <= 0) {
                    return ResponseCreator.creatOk(null, ResCode.ER_70014, "激活码不存在");
                }

                long cutTime = System.currentTimeMillis();
                String vip_start_time = TimeUtils.convert(cutTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
                VipEnumBean vipEnumBean = VipEnumDB.findVipEnum(activeCodeVipType);
                String vip_end_time = TimeUtils.convert(cutTime + vipEnumBean.vip_duration * 1000,
                        TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);

                MockStatUserBean mockStatUserBean = MockStatUserDB.findByStatId(stat_id);
                if (mockStatUserBean == null) {
                    return ResponseCreator.creatOk(null, ResCode.ER_70014, "激活码登录失败");
                }
                userId8 = mockStatUserBean.user_id;
                userBean = UserDB.findUserByUserId(userId8);

                if (StringUtils.isEmpty(userBean.vip_end_time)) {
                    //用户首次购买时，直接修改起止时间
                    UserDB.updateVipType(userId8, activeCodeVipType, vip_start_time, vip_end_time);
                } else if (TimeUtil.timePass(userBean.vip_end_time) >= 0) {
                    //用户的会员时间已经到期，再次购买时，直接修改起止时间
                    UserDB.updateVipType(userId8, activeCodeVipType, vip_start_time, vip_end_time);
                } else {
                    //用户的会员时间没有到期，再次购买时，应该是从用户会员结束时间开始续费时间

                    String startTime = userBean.vip_end_time;
                    long userEndTimeStamp = TimeParseUtil.parseYYYYMMDDHHmmss(userBean.vip_end_time).getTimeInMillis();
                    String endTime = TimeUtils.convert(userEndTimeStamp + vipEnumBean.vip_duration * 1000,
                            TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);

                    UserDB.updateVipType(userId8, activeCodeVipType, startTime, endTime);
                }
                //重新查询获取 最新用户数据
                userBean = UserDB.findUserByUserId(userId8);

                ActiveDB.update(activeCode, userId8);

            }
        }

        {
            //检查此userId号是否被冻结
            FreezeUserBean freezeUserBean = FreezeUserDB.findFreezeByUserId(userBean.user_id);
            if (freezeUserBean != null) {
                String errMsg = freezeUserBean.reason;
                if (StringUtils.isEmpty(errMsg)) {
                    errMsg = "此账户已被冻结";
                }
                if (StringUtils.isNotEmpty(freezeUserBean.free_time)) {
                    errMsg += "，解冻时间" + freezeUserBean.free_time;
                }
                return ResponseCreator.creatOk(null, ResCode.ER_10014, errMsg);
            }
        }

        //检查是否换机登录
        MockStatBean mockStatBean = MockStatUserDB.findUserDB("", userBean.user_id);

        if (mockStatBean == null) {
            String manufacturer = request.getHeader("manufacturer");
            String android_version = "";
            String appVersionName = request.getHeader("appVersionName");
            String app_channel = request.getHeader("channel");
            String client_os = request.getHeader("os");
            String ip = request.getRemoteAddr();

            String first_use_time = TimeUtils.convert(System.currentTimeMillis(), TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
            String create_time = first_use_time;
            String update_time = first_use_time;

            long threeDayMillisecond = 10 * 60 * 1000;
            String free_trial_end_time = TimeUtils.convert(System.currentTimeMillis() + threeDayMillisecond,
                    TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);

            MockStatUserDB.insertDB(stat_id, userBean.user_id, first_use_time, create_time, update_time, free_trial_end_time,
                    brand, model, manufacturer, android_version, appVersionName, app_channel, client_os, ip, "");

            mockStatBean = MockStatUserDB.findUserDB("", userBean.user_id);
        }

        if (mockStatBean != null && StringUtils.isNotEmpty(brand) && StringUtils.isNotEmpty(model)
                && StringUtils.isNotEmpty(mockStatBean.brand) && StringUtils.isNotEmpty(mockStatBean.model)) {
            //具备检查换机的条件，才来判断是否换机了
            if (StringUtils.equals(brand, mockStatBean.brand) && StringUtils.equals(model, mockStatBean.model)) {
                //没有换机，可以正常继续执行
            } else {
                //检测到换机了，登录失败
                String errMsg = String.format("登录失败，检测到您已更换设备，当前账号的绑定设备类型为:%s %s。" +
                                "\n\n同一个账号不允许随意切换设备，以防止一人购买会员但却多人蹭用的场景，如需继续更换设备，请付费解绑" +
                                "\n\nuserId = %s"+
                                "\n\nstatId = %s",
                        mockStatBean.brand, mockStatBean.model, mockStatBean.user_id, mockStatBean.stat_id);

                LoginUserVM loginUserVM = new LoginUserVM();
                loginUserVM.user = userBean;

                return ResponseCreator.creatOk(loginUserVM, ResCode.ER_10015, errMsg);
            }
        }


        //////////////////////////////////////
        ///////////////  登录成功  ////////////
        // 删除 已经存在的 或 过期的 token 记录
        AuthTokenDB.clearTokenByUserid(userBean.user_id);

        //创建新 token 并保存db
        AuthTokenBean newToken = new AuthTokenBean();
        newToken.user_id = userBean.user_id;
        newToken.auth_token = TokenHelper.createToken(userBean.user_id);
        long currentTime = System.currentTimeMillis();
        long validTime = currentTime + 30 * 24 * 60 * 60 * 1000; //默认 30天 有效期
        newToken.create_time = TimeUtils.convert(currentTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        newToken.valid_date = TimeUtils.convert(validTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        AuthTokenDB.insert(newToken);

        LoginUserVM loginUserVM = new LoginUserVM();
        loginUserVM.user = userBean;
        loginUserVM.auth_token = newToken.auth_token;

        loginUserVM.stat_bean = MockStatUserDB.findUserDB("", userBean.user_id);

        if (userBean.vip_type > 0) {
            loginUserVM.vip_bean = VipEnumDB.findVipEnum(userBean.vip_type);
        }



        return ResponseCreator.creatOk(loginUserVM, ResCode.CODE_OK, "登录成功");
    }

    @Override
    public ResponseEntity<ResultBean<LoginUserVM>> loginAutoRegister(HttpServletRequest request) {
        String brand = request.getHeader("brand");
        String model = request.getHeader("model");
        String stat_id = request.getHeader("stat_id");

        MockStatUserBean mockStatUserBean = MockStatUserDB.findByStatId(stat_id);

        if (mockStatUserBean != null) {
            UserBean userBean = UserDB.findUserByUserId(mockStatUserBean.user_id);

            if (userBean != null) {
                //创建新 token 并保存db
                AuthTokenBean newToken = new AuthTokenBean();
                newToken.user_id = userBean.user_id;
                newToken.wx_unionid = null;
                newToken.auth_token = TokenHelper.createToken(userBean.user_id);
                long currentTime = System.currentTimeMillis();
                long validTime = currentTime + 3000 * 24 * 60 * 60 * 1000; //默认 3000天 有效期
                newToken.create_time = TimeUtils.convert(currentTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
                newToken.valid_date = TimeUtils.convert(validTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
                AuthTokenDB.insert(newToken);

                /////////

                LoginUserVM loginUserVM = new LoginUserVM();
                loginUserVM.user = userBean;
                loginUserVM.auth_token = newToken.auth_token;
                loginUserVM.baby_relation_v_m_list = BabyRelationDB.getBabyRelationVm(userBean.user_id);

                loginUserVM.stat_bean = MockStatUserDB.findUserDB("", userBean.user_id);

                if (userBean.vip_type > 0) {
                    loginUserVM.vip_bean = VipEnumDB.findVipEnum(userBean.vip_type);
                }

                return ResponseCreator.creatOk(loginUserVM, ResCode.CODE_OK, "登录成功");
            }
        }


        //创建用户 并保存db
        UserBean userBeanNew = new UserBean();
        userBeanNew.user_id = UUID.randomUUID().toString();
        userBeanNew.phone_number = userBeanNew.user_id.substring(0, 8);
        UserDB.createUserByPhone(userBeanNew);

        //创建新 token 并保存db
        AuthTokenBean newToken = new AuthTokenBean();
        newToken.user_id = userBeanNew.user_id;
        newToken.phone_number = userBeanNew.phone_number;
        newToken.auth_token = TokenHelper.createToken(userBeanNew.user_id);
        long currentTime = System.currentTimeMillis();
        long validTime = currentTime + 30 * 24 * 60 * 60 * 1000; //默认 30天 有效期
        newToken.create_time = TimeUtils.convert(currentTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        newToken.valid_date = TimeUtils.convert(validTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        AuthTokenDB.insert(newToken);

        LoginUserVM loginUserVM = new LoginUserVM();
        loginUserVM.user = userBeanNew;
        loginUserVM.auth_token = newToken.auth_token;
        SMS_DB.disableAuthCodeLoginRecord(userBeanNew.phone_number, SMS_DB.SMS_TYPE_LOGIN); //登录成功后，清除其有效状态，防止重用

        String manufacturer = request.getHeader("manufacturer");
        String android_version = "";
        String appVersionName = request.getHeader("appVersionName");
        String app_channel = request.getHeader("channel");
        String client_os = request.getHeader("os");
        String ip = request.getRemoteAddr();

        String first_use_time = TimeUtils.convert(System.currentTimeMillis(), TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        String create_time = first_use_time;
        String update_time = first_use_time;

        long threeDayMillisecond = 10 * 60 * 1000;
        String free_trial_end_time = TimeUtils.convert(System.currentTimeMillis() + threeDayMillisecond,
                TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);

        MockStatUserDB.insertDB(stat_id, userBeanNew.user_id, first_use_time, create_time, update_time, free_trial_end_time,
                brand, model, manufacturer, android_version, appVersionName, app_channel, client_os, ip, "");


        return ResponseCreator.creatOk(loginUserVM, ResCode.CODE_OK, "创建账户成功");
    }

    @Override
    public ResponseEntity<ResultBean<LoginUserVM>> loginStatId(HttpServletRequest request) {

        String brand = request.getHeader("brand");
        String model = request.getHeader("model");
        String stat_id = request.getHeader("stat_id");

        UserBean userBean = UserDB.findUserByStatId(stat_id);

        if (userBean == null) {
            return ResponseCreator.creatOk(null, ResCode.ER_10017, "服务器内部错误");
        }

        //检查此微信号是否被冻结
        {
            FreezeUserBean freezeUserBean = FreezeUserDB.findFreezeByStatId(stat_id);
            if (freezeUserBean != null) {
                String errMsg = freezeUserBean.reason;
                if (StringUtils.isEmpty(errMsg)) {
                    errMsg = "此账户已被冻结";
                }
                if (StringUtils.isNotEmpty(freezeUserBean.free_time)) {
                    errMsg += "，解冻时间" + freezeUserBean.free_time;
                }
                return ResponseCreator.creatOk(null, ResCode.ER_10014, errMsg);
            }
        }

        //检查是否换机登录
        MockStatBean mockStatBean = MockStatUserDB.findUserDB("", userBean.user_id);
        if (mockStatBean != null && StringUtils.isNotEmpty(brand) && StringUtils.isNotEmpty(model)
                && StringUtils.isNotEmpty(mockStatBean.brand) && StringUtils.isNotEmpty(mockStatBean.model)) {
            //具备检查换机的条件，才来判断是否换机了
            if (StringUtils.equals(brand, mockStatBean.brand) && StringUtils.equals(model, mockStatBean.model)) {
                //没有换机，可以正常继续执行
            } else {
                //检测到换机了，登录失败
                String errMsg = String.format("登录失败，检测到您已更换设备，当前账号的绑定设备类型为:%s %s。" +
                                "\n\n同一个账号不允许随意切换设备，以防止一人购买会员但却多人蹭用的场景，如需继续更换设备，请付费解绑" +
                                "\n\nuserId = %s"+
                                "\n\nstatId = %s",
                        mockStatBean.brand, mockStatBean.model, mockStatBean.user_id, mockStatBean.stat_id);

                LoginUserVM loginUserVM = new LoginUserVM();
                loginUserVM.user = userBean;

                return ResponseCreator.creatOk(loginUserVM, ResCode.ER_10015, errMsg);
            }
        }

        //////////////////////////////////////
        ///////////////  登录成功  ////////////
        // 删除 已经存在的 或 过期的 token 记录
        AuthTokenDB.clearTokenByUserid(userBean.user_id);

        //创建新 token 并保存db
        AuthTokenBean newToken = new AuthTokenBean();
        newToken.user_id = userBean.user_id;
        newToken.wx_unionid = null;
        newToken.auth_token = TokenHelper.createToken(userBean.user_id);
        long currentTime = System.currentTimeMillis();
        long validTime = currentTime + 3000 * 24 * 60 * 60 * 1000; //默认 3000天 有效期
        newToken.create_time = TimeUtils.convert(currentTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        newToken.valid_date = TimeUtils.convert(validTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        AuthTokenDB.insert(newToken);

        LoginUserVM loginUserVM = new LoginUserVM();
        loginUserVM.user = userBean;
        loginUserVM.auth_token = newToken.auth_token;
        loginUserVM.baby_relation_v_m_list = BabyRelationDB.getBabyRelationVm(userBean.user_id);

        loginUserVM.stat_bean = MockStatUserDB.findUserDB("", userBean.user_id);

        if (userBean.vip_type > 0) {
            loginUserVM.vip_bean = VipEnumDB.findVipEnum(userBean.vip_type);
        }

        return ResponseCreator.creatOk(loginUserVM, ResCode.CODE_OK, "登录成功");
    }

    @Override
    public ResponseEntity<ResultBean<LoginUserVM>> createUserByPhone(String phone, String authCode) {
        if (StringUtils.length(phone) != 11) {
            return ResponseCreator.creatOk(null, ResCode.ER_10020, "手机号格式不正确");
        }
        if (StringUtils.length(authCode) != 4) {
            return ResponseCreator.creatOk(null, ResCode.ER_10021, "验证码错误");
        }

        //检查此手机号是否已注册过
        UserBean userBean = UserDB.findUserByPhone(phone);
        if (userBean != null) {
            return ResponseCreator.creatOk(null, ResCode.ER_10022, "此手机号已注册，请直接登录");
        }

        //检查手机号与验证码是否匹配
        if (!SMS_DB.checkAuthCodeLogin(phone, authCode)) {
            return ResponseCreator.creatOk(null, ResCode.ER_10011, "验证码错误");
        }

        //创建用户 并保存db
        UserBean userBeanNew = new UserBean();
        userBeanNew.user_id = UUID.randomUUID().toString();
        userBeanNew.phone_number = phone;
        UserDB.createUserByPhone(userBeanNew);

        //创建新 token 并保存db
        AuthTokenBean newToken = new AuthTokenBean();
        newToken.user_id = userBeanNew.user_id;
        newToken.phone_number = phone;
        newToken.auth_token = TokenHelper.createToken(userBeanNew.user_id);
        long currentTime = System.currentTimeMillis();
        long validTime = currentTime + 30 * 24 * 60 * 60 * 1000; //默认 30天 有效期
        newToken.create_time = TimeUtils.convert(currentTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        newToken.valid_date = TimeUtils.convert(validTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        AuthTokenDB.insert(newToken);

        LoginUserVM loginUserVM = new LoginUserVM();
        loginUserVM.user = userBeanNew;
        loginUserVM.auth_token = newToken.auth_token;
        SMS_DB.disableAuthCodeLoginRecord(phone, SMS_DB.SMS_TYPE_LOGIN); //登录成功后，清除其有效状态，防止重用
        return ResponseCreator.creatOk(loginUserVM, ResCode.CODE_OK, "创建账户成功");
    }

    @Override
    public ResponseEntity<ResultBean<LoginUserVM>> createUserByRegister(String statid, String userName, String userPwd) {

        if (StringUtils.length(userName) < 4) {
            return ResponseCreator.creatOk(null, ResCode.ER_10020, "账号长度至少4位");
        }

        if (StringUtils.length(userPwd) < 8) {
            return ResponseCreator.creatOk(null, ResCode.ER_10021, "密码长度至少4位");
        }

        //检查此设备是否已注册过
        UserBean userBeanStat = UserDB.findUserByStatId(statid);
        if (userBeanStat != null) {
            return ResponseCreator.creatOk(null, ResCode.ER_10022, "此设备已注册账号" + userBeanStat.phone_number + "，请直接登录");
        }

        //检查此手机号是否已注册过
        UserBean userBean = UserDB.findUserByPhone(userName);
        if (userBean != null) {
            return ResponseCreator.creatOk(null, ResCode.ER_10022, "此账号已被注册");
        }

        //创建用户 并保存db
        UserBean userBeanNew = new UserBean();
        userBeanNew.user_id = UUID.randomUUID().toString();
        userBeanNew.phone_number = userName;
        userBeanNew.pwd = userPwd;
        userBeanNew.stat_id = statid;
        UserDB.createUserByRegister(userBeanNew);

        //创建新 token 并保存db
        AuthTokenBean newToken = new AuthTokenBean();
        newToken.user_id = userBeanNew.user_id;
        newToken.phone_number = userName;
        newToken.auth_token = TokenHelper.createToken(userBeanNew.user_id);
        long currentTime = System.currentTimeMillis();
        long validTime = currentTime + 3000 * 24 * 60 * 60 * 1000; //默认 30天 有效期
        newToken.create_time = TimeUtils.convert(currentTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        newToken.valid_date = TimeUtils.convert(validTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        AuthTokenDB.insert(newToken);

        return ResponseCreator.creatOk(null, ResCode.CODE_OK, "创建账户成功\n账号：" + userName);
    }

    @Override
    public ResponseEntity<ResultBean<LoginUserVM>> createUserByWX(String unionid, String nickname, String headimgurl) {
        //检查此微信号是否已注册过
        UserBean userBean = UserDB.findUserByWXUnionid(unionid);
        if (userBean != null) {
            return ResponseCreator.creatOk(null, ResCode.ER_10024, "此微信号已注册，请直接登录");
        }

        //创建用户 并保存db
        UserBean userBeanNew = new UserBean();
        userBeanNew.user_id = UUID.randomUUID().toString();
        userBeanNew.nick_name = nickname;
        userBeanNew.avatar = headimgurl;
        if (UserDB.createUserByWX(userBeanNew, unionid, nickname, headimgurl) < 0) {

            nickname = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 8);
            userBeanNew.nick_name = nickname;

            if (UserDB.createUserByWX(userBeanNew, unionid, nickname, headimgurl) < 0) {
                return ResponseCreator.creatOk(null, ResCode.ER_10023, "微信号注册时操作数据库失败");
            }
        }

        //创建新 token 并保存db
        AuthTokenBean newToken = new AuthTokenBean();
        newToken.user_id = userBeanNew.user_id;
        newToken.wx_unionid = unionid;
        newToken.auth_token = TokenHelper.createToken(userBeanNew.user_id);
        long currentTime = System.currentTimeMillis();
        long validTime = currentTime + 30 * 24 * 60 * 60 * 1000; //默认 30天 有效期
        newToken.create_time = TimeUtils.convert(currentTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        newToken.valid_date = TimeUtils.convert(validTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        AuthTokenDB.insert(newToken);

        LoginUserVM loginUserVM = new LoginUserVM();
        loginUserVM.user = userBeanNew;
        loginUserVM.auth_token = newToken.auth_token;
        return ResponseCreator.creatOk(loginUserVM, ResCode.CODE_OK, "创建账户成功\n账号：" + userBeanNew);
    }

    @Override
    public ResponseEntity<ResultBean<LoginUserVM>> createUserByQQ(HttpServletRequest request, String qqOpenId,
                                                                  String nickname, String headimgurl) {

        byte[] bytes = Base64.getDecoder().decode(headimgurl);
        headimgurl = new String(bytes);

        //检查此QQ号是否已注册过
        UserBean userBean = UserDB.findUserByQQOpenid(qqOpenId);
        if (userBean != null) {
            return ResponseCreator.creatOk(null, ResCode.ER_10025, "此QQ号已注册，请直接登录");
        }

        String stat_id = request.getHeader("stat_id");
        if (StringUtils.isNotBlank(stat_id)) {
            UserBean statBean = UserDB.findUserByQQOpenidAndStatId(stat_id);

            if (statBean != null) {
                return ResponseCreator.creatOk(null, ResCode.ER_10026,
                        "此设备上已登录过其它QQ，一个设备只允许绑定一个QQ，否则会出现通过无限创建QQ号来盗用本软件的场景");
            }
        }

        //创建用户 并保存db
        UserBean userBeanNew = new UserBean();
        userBeanNew.user_id = UUID.randomUUID().toString();
        userBeanNew.nick_name = nickname;
        userBeanNew.avatar = headimgurl;
        if (UserDB.createUserByQQ(userBeanNew, qqOpenId, nickname, headimgurl, stat_id) < 0) {
            return ResponseCreator.creatOk(null, ResCode.ER_10023, "QQ号注册时操作数据库失败");
        }

        //创建新 token 并保存db
        AuthTokenBean newToken = new AuthTokenBean();
        newToken.user_id = userBeanNew.user_id;
        newToken.qq_openid = qqOpenId;
        newToken.auth_token = TokenHelper.createToken(userBeanNew.user_id);
        long currentTime = System.currentTimeMillis();
        long validTime = currentTime + 30 * 24 * 60 * 60 * 1000; //默认 30天 有效期
        newToken.create_time = TimeUtils.convert(currentTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        newToken.valid_date = TimeUtils.convert(validTime, TimeUtils.TIME_FORMAT_YYYY_MM_DD_HH_MM_SS);
        AuthTokenDB.insert(newToken);

        LoginUserVM loginUserVM = new LoginUserVM();
        loginUserVM.user = userBeanNew;
        loginUserVM.auth_token = newToken.auth_token;
        return ResponseCreator.creatOk(loginUserVM, ResCode.CODE_OK, "创建账户成功");
    }


    @Override
    public ResponseEntity<ResultBean<String>> sendAuthCodeSMS(HttpServletRequest request, String phone, boolean send) {
        if (StringUtils.length(phone) != 11) {
            return ResponseCreator.creatOk(null, ResCode.ER_10000, "手机号格式不正确");
        }

        //检查ip攻击
        String ip = IpUtil.getIpAddr(request);
        if (StringUtils.isNotEmpty(ip)) {
            String today = TimeUtils.convert(System.currentTimeMillis(), TimeUtils.TIME_FORMAT_YYYY_MM_DD_2) + " 00:00:00";
            //限制每个ip，每天最多发10次验证码
            if (SMS_DB.checkIpTodaySMSCount(ip, today) >= MAX_SMS_COUNT_IP) {
                return ResponseCreator.creatOk(null, ResCode.ER_10004, "今天验证码已超出次数限制，请明天再试");
            }
        }

        //检查同一个手机当天是否超量
        if (SMS_DB.checkPhoneSMSCount(phone, TimeUtils.getTodayStart(), TimeUtils.getTodayEnd()) >= MAX_SMS_COUNT_PHONE) {
            return ResponseCreator.creatOk(null, ResCode.ER_10005, "今天此手机号的验证码已超出次数限制，请明天再试");
        }

        //检查时间间隔是否超过1分钟
        if (!SMS_DB.checkSMSCodeIntervalValid(phone, SMS_DB.SMS_TYPE_LOGIN)) {
            return ResponseCreator.creatOk(null, ResCode.ER_10003, "请勿频繁发送注册验证码，请1分钟后再尝试");
        }

        String code = RandomUtils.generateValidCode(4);
        LogUtils.warn("生成的验证码:" + code);

        //插入发送记录
        boolean insertDBFlag = SMS_DB.insertSMS(phone, code, SMS_DB.SMS_TYPE_LOGIN, ip,
                SMSHelper.Const.LOGIN_SIGN_NAME, SMSHelper.Const.LOGIN_TEMPLATE_CODE, send);
        if (!insertDBFlag) {
            return ResponseCreator.creatOk(null, ResCode.ER_10002, "发送验证码失败");
        }

        try {
            if (send) {
                //发送短信
                CommonResponse response = SMSHelper.sendSMS_Login(phone, code);
                LogUtils.warn(response.getData());
            }

            return ResponseCreator.creatOk(null, ResCode.CODE_OK, "验证码已发送至" + phone);
        } catch (Exception e) {
            return ResponseCreator.creatOk(null, ResCode.ER_10001, "发送验证码失败，" + e.getMessage());
        }
    }

    @Override
    public ResponseEntity<ResultBean<LoginUserVM>> refresh(String statId) {
        String userId = TokenHelper.getUserIdByToken();
        UserBean userBean = UserDB.findUserByUserId(userId);

        LoginUserVM loginUserVM = new LoginUserVM();
        loginUserVM.user = userBean;
        loginUserVM.auth_token = TokenHelper.getRequestToken();

        if (userBean.vip_type > 0) {
            loginUserVM.vip_bean = VipEnumDB.findVipEnum(userBean.vip_type);
        }

        loginUserVM.baby_relation_v_m_list = BabyRelationDB.getBabyRelationVm(userBean.user_id);
        loginUserVM.stat_bean = MockStatUserDB.findUserDB(statId, userBean.user_id);

        return ResponseCreator.creatOk(loginUserVM, ResCode.CODE_OK, "获取用户信息成功");
    }

    @Override
    public ResponseEntity<ResultBean<Void>> report(String appChannel, String phone, String userId, String reportContent) {

        List<AppConfigBean> beanList = AppConfigDB.getAppConfigData(appChannel);

        AppConfigBean wxBean = CollectionUtils.findFirst(beanList, new CollectionUtils.Function1<AppConfigBean, Boolean>() {
            @Override
            public boolean accept(AppConfigBean appConfigBean) {
                return "wx_no".equals(appConfigBean.config_key);
            }
        });

        boolean insertResult = false;
        if (wxBean != null && StringUtils.isNotEmpty(wxBean.config_value)) {
            insertResult = ReportDB.insert(phone, userId, reportContent, "请联系客服微信"+wxBean.config_value);
        } else {
            insertResult = ReportDB.insert(phone, userId, reportContent);
        }

        if (insertResult) {
            return ResponseCreator.creatOk(null, ResCode.CODE_OK, "反馈提交成功");
        } else {
            return ResponseCreator.creatOk(null, ResCode.ER_50000, "反馈提交失败");
        }
    }

    @Override
    public ResponseEntity<ResultBean<List<ReportBean>>> getReportList(String userId) {
        return ResponseCreator.creatOk(ReportDB.getNoticeList(userId), ResCode.CODE_OK, "反馈提交成功");
    }

    @Override
    public ResponseEntity<ResultBean<Void>> modifyUserData(String avatar, String nick_name, String birthday, int gender) {
        String userId = TokenHelper.getUserIdByToken();
        if (UserDB.updateUserData(userId, avatar, nick_name, birthday, gender)) {
            return ResponseCreator.creatOk(null, ResCode.CODE_OK, "保存成功");
        } else {
            return ResponseCreator.creatOk(null, ResCode.ER_10030, "保存失败");
        }
    }

    @Override
    public ResponseEntity<ResultBean<Void>> modifyPwd(String pwd_key_md5) {
        String userId = TokenHelper.getUserIdByToken();
        if (UserDB.updateUserPwd(userId, pwd_key_md5)) {
            return ResponseCreator.creatOk(null, ResCode.CODE_OK, "修改成功");
        } else {
            return ResponseCreator.creatOk(null, ResCode.ER_10030, "修改失败");
        }
    }

    @Override
    public ResponseEntity<ResultBean<String>> startSign() {
        String userId = TokenHelper.getUserIdByToken();

        UserBean userBean = UserDB.findUserByUserId(userId);

        if (userBean == null) {
            return ResponseCreator.creatOk(null, ResCode.ER_10031, "签到失败");
        } else if (userBean.vip_type == VipTypeEnum.Year.value || userBean.vip_type == VipTypeEnum.Forever.value) {

            SignBean signBean = SignRecordDB.getSignBean(userId);

            //计算当前已连续签到N天
            java.util.Calendar calendar = java.util.Calendar.getInstance();
            calendar.add(java.util.Calendar.DAY_OF_MONTH, -1);

            Collections.sort(signBean.sign_date_list);
            List<java.util.Calendar> signCalendarList = convertCalendarList(signBean.sign_date_list);

            int maxSignCount = 0;
            int size = CollectionUtils.size(signCalendarList);


            for (int i = size - 1; i >= 0; i--) {
                if (compare(calendar, signCalendarList.get(i))) {
                    calendar.add(java.util.Calendar.DAY_OF_MONTH, -1);
                    maxSignCount++;
                } else {
                    break;
                }
            }

            if (maxSignCount >= 45) {
                //高级会员，连续签到45天后，只会提示成功，实际没有计数签到，以免用户要返钱
                return ResponseCreator.creatOk(null, ResCode.CODE_OK, "签到成功");
            } else {

                if (SignRecordDB.createSignRecord(userId) > 0) {
                    return ResponseCreator.creatOk(null, ResCode.CODE_OK, "签到成功");
                } else {
                    return ResponseCreator.creatOk(null, ResCode.ER_10031, "签到失败");
                }
            }
        }

        if (SignRecordDB.createSignRecord(userId) > 0) {
            return ResponseCreator.creatOk(null, ResCode.CODE_OK, "签到成功");
        } else {
            return ResponseCreator.creatOk(null, ResCode.ER_10031, "签到失败");
        }
    }

    private boolean compare(java.util.Calendar c1, java.util.Calendar c2) {
        if (c1.get(java.util.Calendar.YEAR) == c2.get(java.util.Calendar.YEAR)
                && c1.get(java.util.Calendar.MONTH) == c2.get(java.util.Calendar.MONTH)
                && c1.get(java.util.Calendar.DAY_OF_MONTH) == c2.get(java.util.Calendar.DAY_OF_MONTH)) {
            return true;
        }
        return false;
    }

    private List<java.util.Calendar> convertCalendarList(List<String> signDateList) {
        if (signDateList == null) {
            return null;
        }

        List<java.util.Calendar> calendarList = new ArrayList<>();

        for (int i = 0; i < signDateList.size(); i++) {
            calendarList.add(TimeParseUtil.parseYYYYMMDD(signDateList.get(i)));
        }

        return calendarList;
    }

    @Override
    public ResponseEntity<ResultBean<SignBean>> getSignData() {
        String userId = TokenHelper.getUserIdByToken();

        SignBean signBean = SignRecordDB.getSignBean(userId);

        if (signBean != null) {
            return ResponseCreator.creatOk(signBean, ResCode.CODE_OK, "获取签到数据成功");
        } else {
            return ResponseCreator.creatOk(null, ResCode.ER_10031, "获取签到数据失败");
        }
    }

}
